package com.xspace.android.xafcommon.network.task;

import java.io.IOException;
import java.util.Date;
import java.util.Vector;

import org.apache.http.conn.ConnectTimeoutException;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.xspace.android.xafcommon.network.HttpConnectWrapper;
import com.xspace.android.xafcommon.network.NetConstant;
import com.xspace.android.xafcommon.network.exception.DecodeMessageException;
import com.xspace.android.xafcommon.network.exception.EncodeMessageException;
import com.xspace.android.xafcommon.network.message.AResponseMsg;
import com.xspace.android.xafcommon.util.LogUtils;

public final class ThreadPool {
    private static final String TAG = "ThreadPool";
    /* The default pool thread number */
    public int worker_num = 2;
    /* Has the task of add number */
    private int taskCounter = 0;
    private Vector<ITask> mTaskQueue = new Vector<ITask>();
    private static Vector<Integer> mDoingTasks = new Vector<Integer>();
    /* All threads in the pool */
    public PoolWorker[] workers;

    /**
     * @param num - Thread pool thread number
     */
    public ThreadPool(int num) {
        this.worker_num = num;
        workers = new PoolWorker[worker_num];
        for (int i = 0; i < workers.length; i++) {
            workers[i] = new PoolWorker(i);
        }
    }

    /**
     * Adding new task Every increase a new task is to awaken task queue
     *
     * @param newTask
     */
    public void addTask(ITask newTask) {
        synchronized (mTaskQueue) {
            newTask.setTaskId(newTask.getRequest().getSerId());
            newTask.setSubmitTime(new Date());
            mTaskQueue.add(newTask);
            mTaskQueue.notifyAll();
        }
    }

    /**
     * Batch adding new task
     *
     * @param taskes
     */
    public void batchAddTask(Task[] taskes) {
        if (null == taskes || 0 == taskes.length) {
            return;
        }

        synchronized (mTaskQueue) {
            for (int i = 0; i < taskes.length; i++) {
                if (taskes[i] == null) {
                    continue;
                }
                taskes[i].setTaskId(++taskCounter);
                taskes[i].setSubmitTime(new Date());
                mTaskQueue.add(taskes[i]);
            }
            mTaskQueue.notifyAll();
        }
    }

    /**
     * @param serId void
     * @Description: According to the seral number cancel task
     */
    public void cancelTask(int serId) {
        synchronized (mTaskQueue) {
            ITask task = null;
            int size = mTaskQueue.size();
            for (int i = 0; i < size; i++) {
                task = mTaskQueue.get(i);
                if (null == task) {
                    continue;
                }
                if (task.getRequest().getSerId() == serId) {
                    mTaskQueue.remove(i);
                    break;
                }
            }
        }
        mDoingTasks.removeElement(serId);
    }

    /**
     * @return String
     * @Description: Thread pool information
     */
    public String getInfo() {
        StringBuffer sb = new StringBuffer();
        sb.append("\nTask Queue Size:" + mTaskQueue.size());
        for (int i = 0; i < workers.length; i++) {
            sb.append("\nWorker Thread " + i + " is " + ((workers[i].isWaiting()) ? "Waiting." : "Running."));
        }
        return sb.toString();
    }

    /**
     * @return boolean
     * @Description: Check job threads in operation
     */
    protected boolean isRuning() {
        boolean flag = false;
        for (int i = 0; i < workers.length; i++) {
            flag = ((workers[i].isWaiting()) ? false : true);
            if (flag) {
                break;
            }
        }
        return flag;
    }

    /**
     * @Description: Destoryed thread pool
     */
    public synchronized void destroy() {
        for (int i = 0; i < worker_num; i++) {
            workers[i].stopWorker();
            workers[i] = null;
        }
        mTaskQueue.clear();
    }

    private class PoolWorker extends Thread {
        private int index = -1;
        /* The worker thread ara effeactive */
        private boolean isRunning = true;
        /* This work whether the thread can perform the new task */
        private boolean isWaiting = true;

        public PoolWorker(int index) {
            this.index = index;
            start();
        }

        public void stopWorker() {
            this.isRunning = false;
        }

        public boolean isWaiting() {
            return this.isWaiting;
        }

        /**
         * Cirulation mission
         */
        public void run() {
            while (isRunning) {
                ITask task = null;
                synchronized (mTaskQueue) {
                    while (mTaskQueue.isEmpty()) {
                        try {
                            /*
                             * The task for the empty queue,waiting for the new
							 * task to join and awakened
							 */
                            mTaskQueue.wait();
                        } catch (InterruptedException ie) {
                            ie.printStackTrace();
                        }
                    }
					/* Remove task execution */
                    task = (Task) mTaskQueue.remove(0);
                }

                if (null == task) {
                    continue;
                }

                task.setBeginExceuteTime(new Date());
                mDoingTasks.add(new Integer(task.getRequest().getSerId()));

                isWaiting = false;
                int status = NetConstant.TaskStatus.SUCCESS;
                String url = task.getRequest().getURL();
                try {
                    byte[] data = null;
                    int wayFlag = task.getRequest().getRequestWay();
                    AResponseMsg response = (AResponseMsg) task.getResponse();
                    if (wayFlag == 0) {// get
                        data = (new HttpConnectWrapper()).httpGet(url, task.getRequest().getOtherDate(),
                                task.getRequest().getContentType(), task.getRequest().getValuePair(), response);
                    } else if (wayFlag == 1) {// post
                        data = (new HttpConnectWrapper()).httpPost(url, task.getRequest().getContentType(),
                                task.getRequest().getData(), task.getRequest().getOtherDate(),
                                task.getRequest().getValuePair(), response);
                    }
                    response.parseData(data);
                } catch (EncodeMessageException e) {
                    // News coding abnormal
                    status = NetConstant.TaskStatus.ERROR_ENCODE;
                    e.printStackTrace();
                } catch (DecodeMessageException e) {
                    // News decoding abnormal
                    status = NetConstant.TaskStatus.ERROR_DECODE;
                    e.printStackTrace();
                } catch (IllegalStateException e) {
                    status = NetConstant.TaskStatus.ERROR_NETWORK;
                    e.printStackTrace();
                } catch (ConnectTimeoutException e) {
                    // network exption
                    status = NetConstant.TaskStatus.ERROR_TIMEOUT;
                    e.printStackTrace();
                } catch (IOException e) {
                    // network exption
                    status = NetConstant.TaskStatus.ERROR_NETWORK;
                    e.printStackTrace();
                } catch (Exception e) {
                    // network exption
                    status = NetConstant.TaskStatus.ERROR_NETWORK;
                    e.printStackTrace();
                } finally {
                    task.setFinishTime(new Date());
                    LogUtils.d("子线程" + Thread.currentThread().getId());
                    try {
                        android.os.Message m = mHandler.obtainMessage(status, task);
                        mHandler.sendMessage(m);
                    } catch (Exception e) {
                        ITask currTask = task;
                        AResponseMsg respMsg = (AResponseMsg) currTask.getResponse();
                        if (mDoingTasks.removeElement(currTask.getRequest().getSerId())) {
                            respMsg.result = status;
                            currTask.getListener().notifyTask(respMsg);
                        }
                        e.printStackTrace();
                    }
                    isWaiting = true;
                    task = null;
                }
            }
        }
    }

    public static Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            LogUtils.d("主程序" + Thread.currentThread().getId());
            LogUtils.d("接受到返回数据，handle处理");
            ITask currTask = ((ITask) msg.obj);
            AResponseMsg respMsg = (AResponseMsg) currTask.getResponse();
            if (mDoingTasks.removeElement(currTask.getRequest().getSerId())) {
                respMsg.result = msg.what;
                currTask.getListener().notifyTask(respMsg);
            }
        }
    };
}
